a11y: Compute the label for a GtkATContext
authorEmmanuele Bassi <ebassi@gnome.org>
Fri, 9 Oct 2020 20:23:19 +0000 (21:23 +0100)
committerEmmanuele Bassi <ebassi@gnome.org>
Mon, 12 Oct 2020 15:19:32 +0000 (16:19 +0100)
The ARIA spec defines the mechanism for determining the name of an
accessible element—see Â§4.3 of the WAI-ARIA spec.

We follow the specification as much as it makes sense for GTK to do
so:

 1. if the element is hidden, return an empty string
 1. if the element has a labelled-by relation set, retrieve the
    label of the related element
 2. if the element has a label property set, use the value of
    the property
 3. if neither labelled-by nor label attributes are set, we use
    the role to compute the name:
   - for a `range` role, we return the contents of the value of
     the `value-text` or `value-now` properties
   - for any other role, we return a textual representation of
     the GtkAccessibleRole enumeration value

gtk/gtkatcontext.c
gtk/gtkatcontextprivate.h

index 9b586c26bbfd1d5c98d49e7105e1fa7eb2525de7..fe770cd5c22817c82b76e3e829e7ef602dd8e585 100644 (file)
@@ -725,3 +725,83 @@ gtk_at_context_get_accessible_relation (GtkATContext          *self,
 
   return gtk_accessible_attribute_set_get_value (self->relations, relation);
 }
+
+/*< private >
+ * gtk_at_context_get_label:
+ * @self: a #GtkATContext
+ *
+ * Retrieves the accessible label of the #GtkATContext.
+ *
+ * This is a convenience function meant to be used by #GtkATContext implementations.
+ *
+ * Returns: (transfer full): the label of the #GtkATContext
+ */
+char *
+gtk_at_context_get_label (GtkATContext *self)
+{
+  g_return_val_if_fail (GTK_IS_AT_CONTEXT (self), NULL);
+
+  GtkAccessibleValue *value = NULL;
+
+  if (gtk_accessible_attribute_set_contains (self->states, GTK_ACCESSIBLE_STATE_HIDDEN))
+    {
+      value = gtk_accessible_attribute_set_get_value (self->states, GTK_ACCESSIBLE_STATE_HIDDEN);
+
+      if (gtk_boolean_accessible_value_get (value))
+        return g_strdup ("");
+    }
+
+  if (gtk_accessible_attribute_set_contains (self->properties, GTK_ACCESSIBLE_PROPERTY_LABEL))
+    {
+      value = gtk_accessible_attribute_set_get_value (self->properties, GTK_ACCESSIBLE_PROPERTY_LABEL);
+
+      return g_strdup (gtk_string_accessible_value_get (value));
+    }
+
+  if (gtk_accessible_attribute_set_contains (self->relations, GTK_ACCESSIBLE_RELATION_LABELLED_BY))
+    {
+      value = gtk_accessible_attribute_set_get_value (self->relations, GTK_ACCESSIBLE_RELATION_LABELLED_BY);
+
+      GtkAccessible *rel = gtk_reference_accessible_value_get (value);
+      GtkATContext *rel_context = gtk_accessible_get_at_context (rel);
+
+      return gtk_at_context_get_label (rel_context);
+    }
+
+  GtkAccessibleRole role = gtk_at_context_get_accessible_role (self);
+
+  switch ((int) role)
+    {
+    case GTK_ACCESSIBLE_ROLE_RANGE:
+      {
+        int range_attrs[] = {
+          GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT,
+          GTK_ACCESSIBLE_PROPERTY_VALUE_NOW,
+        };
+
+        for (int i = 0; i < G_N_ELEMENTS (range_attrs); i++)
+          {
+            if (gtk_accessible_attribute_set_contains (self->properties, range_attrs[i]))
+              {
+                value = gtk_accessible_attribute_set_get_value (self->properties, range_attrs[i]);
+                break;
+              }
+          }
+
+        if (value != NULL)
+          return g_strdup (gtk_string_accessible_value_get (value));
+      }
+      break;
+
+    default:
+      break;
+    }
+
+  GEnumClass *enum_class = g_type_class_peek (GTK_TYPE_ACCESSIBLE_ROLE);
+  GEnumValue *enum_value = g_enum_get_value (enum_class, role);
+
+  if (enum_value != NULL)
+    return g_strdup (enum_value->value_nick);
+
+  return g_strdup ("widget");
+}
index 115a057cb7b832589723c5f4b762ca372c5c5949..15da90acfee114010691c93e4dd02d60857c0c60 100644 (file)
@@ -136,6 +136,8 @@ gboolean                gtk_at_context_has_accessible_relation  (GtkATContext
 GtkAccessibleValue *    gtk_at_context_get_accessible_relation  (GtkATContext          *self,
                                                                  GtkAccessibleRelation  relation);
 
+char *                  gtk_at_context_get_label                (GtkATContext          *self);
+
 const char *    gtk_accessible_property_get_attribute_name      (GtkAccessibleProperty property);
 const char *    gtk_accessible_relation_get_attribute_name      (GtkAccessibleRelation relation);
 const char *    gtk_accessible_state_get_attribute_name         (GtkAccessibleState    state);